#!/usr/bin/env python3
# -*- coding:utf-8 -*-
## author : cypro666
## date   : 2014.8.30
"""Wrapper of CSV format file reader and writer"""
import sys
try:
    import csv
except ImportError:
    pass
try:
    from bson.objectid import ObjectId
except ImportError as e:
    sys.stderr.write('reports.py : Can\'t find pymongo module!\n')

from .fileio import FileIO
from .utilities import loadjson, dumpjson
from .debug import time_meter

__all__ = ['CSVReader', 'CSVWriter', 'MongoDoc']


def linefeed(line):
    return line + '\n' if line[-1] != '\n' else line


class _CSVRW(object):
    """Base class of CSVReader and CSVWriter"""
    __slots__ =  ('_file', '_mode')
    def __init__(self, filename, mode):
        self._file = FileIO(filename, mode)
        self._mode = mode
    
    def close(self):
        self._file.close()

    def __enter__(self):
        return self
    
    def __exit__(self, *args):
        self._file.close()
        return False
    


class CSVReader(_CSVRW):
    __slots__ = ()
    """Read csv file"""
    def __init__(self, filename):
        super().__init__(filename, 'r')
        
    def read(self):
        buffer = []
        for line in self._file:
            seps = line.split(',')
            row = tuple(map(lambda s:s.strip(), seps))
            buffer.append(row)
        return buffer
            
    def read_row(self):
        for line in self._file:
            seps = line.split(',')
            yield tuple(map(lambda s:s.strip(), seps))



class CSVWriter(_CSVRW):
    __slots__ = ('_format',)
    """Write csv file"""
    def __init__(self, filename):
        super().__init__(filename, 'w')

    def set_format(self, format, headlines = []):
        self._format = linefeed(format)
        if ',' not in self._format:
            self._format = ','.join(self._format.split(' '))
            if self._format[0] == ',':
                self._format = self._format[1:]
        if self._mode == 'w':
            for line in headlines:
                row = linefeed(line)
                self._file.write(row)

    def write(self, rows):
        assert isinstance(rows, (list,tuple,set))
        for each in rows:
            assert isinstance(each, tuple)
            row = linefeed(self._format % each)
            self._file.write(row)
    
    def write_row(self, row):
        assert isinstance(row, tuple)
        row = linefeed(self._format % row)
        self._file.write(row)
        
    def write_blank(self):
        self._file.write('\n', True)



class MongoDoc(object):
    """output mangodb doc(json) object to text file or csv file, very slow!"""
    @staticmethod
    def write(filename, docs):
        assert filename and hasattr(docs, '__iter__')
        def objhook(obj):
            if '_id' in obj: 
                obj['_id'] = str(obj['_id'])
            return obj
        dumpjson(docs, objhook, filename)

    @staticmethod
    def write_ex(jsonfile, csvfile, format, filter, headlines = []):
        def objhook(obj):
            if '_id' in obj: 
                obj['_id'] = ObjectId(obj['_id'])
            return obj
        with CSVWriter(csvfile) as file:
            file.set_format(format, headlines)
            for d in loadjson(jsonfile, objhook):
                row = filter(d)
                file.write_row(row)


@time_meter(__name__)
def test(csvfile):
    writer = CSVWriter(csvfile)
    writer.set_format('%s, %d, %.2f%%', ['headline', 'name, id, item'])
    writer.write_row(('Jeck', 123, 63.52))
    writer.write_row(('Mike', 234, 55.52))
    writer.write_row(('Abby', 543, 44.52))
    writer.write([('Bob', 222, 44.11),
                  ('Kill', 111, 99.99),
                  ('Sar', 444, 0.1234)])
    writer.close()
    
    reader = CSVReader(csvfile)
    rg = reader.read_row()
    sys.stdout.write(next(rg))
    sys.stdout.write(next(rg))
    sys.stdout.write(next(rg))
    for row in reader.read():
        sys.stdout.write(row)
    reader.close()













